local MAX_ARG = 11

local function toliteral(value)
	local t, v = type(value)
	if t == "nil" then
		v = "nil"
	elseif t == "string" then
		v = string.format("%q", value):gsub("&", "&amp;"):gsub("<", "&lt;"):gsub(">", "&gt;")
	else
		v = tostring(value)
	end
	return string.format("<span class=\"type-%s\">%s</span>", t, v)
end

local function output_event(db, index, output)
	local event, class = db.events[index]
	if event == "update" then
		class = "update"
	elseif event == "UNIT_NAME_UPDATE" then
		class = "unu"
	elseif event == "ADDON_ACTION_BLOCKED" or event == "ADDON_ACTION_FORBIDDEN" then
		class = "error"
	elseif event == "CHAT_MSG_ADDON" or event == "ADDON_LOADED" then
		class = "addon"
	end
	if class then
		output("<tr class=\"action-%s\">", class)
	else
		output("<tr>", class)
	end
	output("<td>%s</td>", toliteral(db.times[index] - db.times[1]))
	output("<td>%s</td>", toliteral(event))
	local start_arg = db.offsets[index]
	local stop_arg = (index == #db.offsets) and #db.args or (db.offsets[index + 1] - 1)
	for i = start_arg, stop_arg do
		output("<td>%s</td>", toliteral(db.args[i]))
	end
	for i = 1, MAX_ARG - (stop_arg - start_arg + 1) do
		output("<td>&nbsp;</td>")
	end
	output("</tr>\n")
end

local HEADER =[[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<title>Recorder</title>
<style type="text/css">
body { background:808080; }
table { border:outset 1px; }
td, th { border:inset 1px; }
td { background:A0A0A0; }
th { background:606060; }
.type-nil { color:red; }
.type-number { color:blue; }
.type-string { color:green; }
.action-update { background-color:lightgray; }
.action-unu { background-color:yellow; }
.action-error { background-color:rgb(255, 180, 180); }
.action-addon { background-color:rgb(180, 220, 180); }
</style>
</head>
<body>
<h1>Recorder offline report</h1>
]]

local function escape(s)
	return s:gsub(".", function (c) return "\\"..string.byte(c) end)
end

local dofile = function (filename)
	local f = io.open(filename, "rb")
	local loader = function ()
		local line = f:read()
		if line then
			local before, content, after = line:match("^([%s+]\")(.*)(\", -- %[%d+%].*)")
			if before and content and after then
				content = escape(content)
				return before..content..after
			end
		end
		return line
	end
	local data = assert(load(loader, filename))
	data()
end

local function report_db(output, db)
	output("<table>\n")
	output("<tr>")
	output("<th>Time</th>")
	output("<th>Event</th>")
	for i = 1, MAX_ARG do
		output("<th>Arg%d</th>", i)
	end
	output("</tr>\n")
	for i = 1, #db.events do
		output_event(db, i, output)
	end
	output("</table>\n")
end

local function main()
	dofile("!!!Recorder3.lua")
	local f = io.open("report.html", "w")
	local output = function (...)
		f:write((string.format(...)))
	end
	output(HEADER)
	output("<h1>Startup Log</h1>")
	report_db(output, RecorderDB)
	if CheckLockDB then
		output("<h1>Lockup Logs</h1>")
		for index, db in ipairs(CheckLockDB) do
			output("<h2>Lockup #%d (%.1f seconds)</h2>", index, db.lockup)
			report_db(output, db)
		end
	end
	output("</body>\n")
	output("</html>\n")
end

main()
